package com.hanter.downloader.demo;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.provider.BaseColumns;
import android.provider.DocumentsContract;
import android.provider.MediaStore;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

public class AndroidUriUtils {

    // 判断文件是否存在，Android Q 卸载后再去查询必须具有 READ_EXTERNAL_STORAGE 权限，否则无法查询到
    // 如果插入已存在的，则会报如下错误：
    // SQLiteConstraintException: UNIQUE constraint failed: files._data (code 2067 SQLITE_CONSTRAINT_UNIQUE)
    public static boolean checkUriExists(Context context, Uri uri, String name, String filePath) {
        String[] projection = new String[]{MediaStore.MediaColumns._ID};
        String selection;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            selection = MediaStore.MediaColumns.DISPLAY_NAME + " = ? AND " + MediaStore.MediaColumns.RELATIVE_PATH + "= ?";
        } else {
            selection = MediaStore.MediaColumns.DISPLAY_NAME + " = ? AND " + MediaStore.MediaColumns.DATA + "= ?";
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            Bundle queryArgs = new Bundle();
            queryArgs.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, selection);
            queryArgs.putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, new String[]{name, filePath});
//            queryArgs.putInt(MediaStore.QUERY_ARG_MATCH_PENDING, MediaStore.MATCH_INCLUDE);
            try (Cursor cursor = context.getContentResolver().query(uri, projection, queryArgs, null)) {
//            try (Cursor cursor = context.getContentResolver().query(uri, projection, null, null)) {
                return cursor != null && cursor.getCount() > 0;
            }
        } else {
            try (Cursor cursor = context.getContentResolver().query(uri, projection, selection, new String[]{name, filePath}, null)) {
                return cursor != null && cursor.getCount() > 0;
            }
        }
    }

    @Nullable
    public static Uri getUriIfExists(Context context, Uri contentUri, String name, String filePath) {
        String[] projection = new String[]{MediaStore.MediaColumns._ID};
        String selection;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            selection = MediaStore.MediaColumns.DISPLAY_NAME + " = ? AND " + MediaStore.MediaColumns.RELATIVE_PATH + " = ?";
        } else {
            selection = MediaStore.MediaColumns.DISPLAY_NAME + " = ? AND " + MediaStore.MediaColumns.DATA + " = ?";
        }

        try (Cursor cursor = context.getContentResolver().query(contentUri, projection, selection, new String[]{name, filePath}, null)) {
            if (cursor != null && cursor.moveToFirst()) {
                long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID));
                return ContentUris.withAppendedId(contentUri, id);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // Android Q RecoverableSecurityException 未授予访问文件权限
    // >= Q Manifest.permission.MANAGE_EXTERNAL_STORAGE
    // < Q Manifest.permission.WRITE_EXTERNAL_STORAGE
    // 参考：https://blog.csdn.net/u013040819/article/details/104909259
    public static int deleteUriById(Context context, Uri contentUri, long id) {
        String where = BaseColumns._ID + "= ?";
        return context.getContentResolver().delete(contentUri, where, new String[]{String.valueOf(id)});
    }

    public static boolean exists(@NonNull Context context, @NonNull Uri uri) {
        String scheme = uri.getScheme();
        if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            if (DocumentsContract.isDocumentUri(context, uri)) {
//                DocumentFile df = DocumentFile.fromSingleUri(context, uri);
//                return df != null && df.exists();
                 return resolveUri(context, uri, DocumentsContract.Document.COLUMN_DOCUMENT_ID);
            } else {
                return resolveUri(context, uri, BaseColumns._ID) && testOpenable(context, uri);
            }
        } else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            return uri.getPath() != null && new File(uri.getPath()).exists();
        } else {
            // 未知类型返回false
            return false;
        }
    }

    private static boolean resolveUri(@NonNull Context context, Uri uri, String column) {
        try (Cursor cursor = context.getContentResolver().query(uri, new String[]{column}, null, null, null, null)) {
            return cursor != null && cursor.moveToFirst();
        }
    }

    private static boolean testOpenable(@NonNull Context context, @NonNull Uri uri) {
        try (ParcelFileDescriptor f = context.getContentResolver().openFileDescriptor(uri, "r")) {
            return f != null;
        } catch (FileNotFoundException e) {
            return false;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

}
